package org.zjvis.datascience.common.aspect;

import cn.hutool.core.util.ArrayUtil;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.slf4j.helpers.MessageFormatter;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.UUID;

/**
 * @description 日志输出切片类
 * @date 2021-12-24
 */
@Component
@Aspect
public class LogAspect {

    private final static Logger logger = LoggerFactory.getLogger("LogAspect");

    public static final String TRACE_ID = "traceId";

    @Pointcut("execution(* org.zjvis..service..*.*(..))) " +
            "and execution(* org.zjvis..util*..*.*(..)))")
    public void serviceAspect() {
    }

    @Pointcut("execution(* org.zjvis..service.dataset.quartz..*.*(..))) ")
    public void quartzServiceAspect() {
    }

    @Pointcut("execution(* org.zjvis.datascience..service..*.*(.., org.zjvis.datascience.common.dto.graph.GraphDTO, ..))")
    public void graphAspect() {
    }

    @Pointcut("execution(* org.zjvis..service.audit..*.*(..))) ")
    public void auditAspect() {
    }

//    @Pointcut("execution(* org.zjvis..web..*.*(..))) && !execution( * org.zjvis..web.socket.WebSocket(..)))")
//    public void webAspect() {
//    }

    @Pointcut("execution(* org.zjvis.datascience..service.dag.TaskManager.getTaskHolder(..)) || "
            + "execution(* org.zjvis.datascience..service.dag.DAGScheduler.schedule(..)) || "
            + "execution(* org.zjvis.datascience..service.FastTextService.getFasttext(..)) ||"
            + "execution(* org.zjvis.datascience..service.dataprovider.GPDataProvider.getDataFromJSON(..))")
    public void excludeAspect() {
    }

    @Pointcut("serviceAspect() && !excludeAspect() && !quartzServiceAspect() && !graphAspect() && !auditAspect()")
    public void aroundAspect() {
    }

    @Around("aroundAspect()")
    public Object around(JoinPoint joinPoint) throws Throwable {
        Object[] param = joinPoint.getArgs();
        if (StringUtils.isEmpty(MDC.get(TRACE_ID))) {
            MDC.put(TRACE_ID, UUID.randomUUID().toString());
        }
        if (joinPoint.getSignature().toString().equals(
                "List org.zjvis.datascience.service.mapper.DatasetMapper.getAllTableDataSourceNeedScheduled()")) {
            return ((ProceedingJoinPoint) joinPoint).proceed();
        }
        logger.info(String
                .format("uri:%s,input:%s,==>begin", joinPoint.getSignature(), paramHandle(param)));
        long start = System.currentTimeMillis();
        Object result = ((ProceedingJoinPoint) joinPoint).proceed();
        long end = System.currentTimeMillis();
        logger.info(String.format("uri:%s,proc_time:%s,<==end", joinPoint.getSignature().toString(),
                end - start));
        return result;
    }

    private String paramHandle(Object[] object) {
        if (ArrayUtil.isEmpty(object)) {
            return "[]";
        }
        if (object.length > 1) {
            return MessageFormatter.arrayFormat(object[0] == null ? "" : object[0].toString(),
                    Arrays.copyOfRange(object, 1, object.length)).getMessage();
        }
        if (object.length == 1 && object[0] instanceof Exception) {
            return ExceptionUtils.getStackTrace((Exception) object[0]);
        }
        return object[0] == null ? "[]" : String.format("[%s]", object[0].toString());
    }

//    @Around("webAspect()")
//   	public Object aroundRest(JoinPoint joinPoint) throws Throwable {
//   		Object[] param = joinPoint.getArgs();
//   		if (StringUtils.isEmpty(MDC.get(TRACE_ID))) {
//   			MDC.put(TRACE_ID, UUID.randomUUID().toString());
//   		}
//
//   		LogUtil.info(LogEnum.REST_REQ, "uri:{},input:{},==>begin", joinPoint.getSignature(), param);
//   		long start = System.currentTimeMillis();
//   		Object result = ((ProceedingJoinPoint) joinPoint).proceed();
//   		long end = System.currentTimeMillis();
//   		LogUtil.info(LogEnum.REST_REQ, "uri:{},proc_time:{},<==end", joinPoint.getSignature().toString(),
//   				end - start);
//   		MDC.clear();
//   		return result;
//   	}

}
